#!/usr/bin/python
#-*- coding:utf-8 -*-

import math

class Areas (object):
	def __init__(self, groundzero=None, scale=1.0):
		self.circles = {}
		self.polygons = {}
		self.groundzero = groundzero
		self.scale = scale
		
	def add_area(self, key, area):
		if key and area:
			if type(area[0]) == type(0):
				self.circles[key] = area
			else:
				self.polygons[key] = area
				
	def get_polygons(self):
		polygons = []
		for poly in self.polygons.items():
			polygons.append((poly[0],
								tuple([self.adjust_coord(coord) for coord in poly[1]])))
		return polygons
		
	def get_circles(self):
		circles = []
		for circ in self.circles.items():
			circles.append((circ[0], (self.adjust_circle(circ[1]))))
		return circles
		
	def adjust_coord(self, coord):
		return (int(coord[0] * self.scale + self.groundzero[0]),
					int(-coord[1] * self.scale + self.groundzero[1]))
					
	def adjust_circle(self, circle):
		return (int(circle[0] * self.scale + self.groundzero[0]),
					int(-circle[1] * self.scale + self.groundzero[1]),
					int(circle[2] * self.scale))
					
	def revert_point(self, point):
		return (int((point[0] - self.groundzero[0]) / self.scale),
					int((self.groundzero[1] - point[1]) / self.scale))
		
	def inside_circle(self, circle, point):
		'''
		circle => (x, y, radius)
		point => (x, y)
		'''
		xc, yc, radius = circle
		xp, yp = point
		
		return math.hypot(xp - xc, yp - yc) <= radius

	# determine if a point is inside a given polygon or not
	# Polygon is a list of (x,y) pairs.
	# http://www.ariel.com.au/a/python-point-int-poly.html
	def inside_polygon(self, polygon, point):
		'''
		polygon => ((x1, y1), (x2, y2), ..., (xn, yn))
		point => (x, y)
		'''
		x, y = point

		n = len(polygon)
		inside = False

		p1x,p1y = polygon[0]
		for i in range(n+1):
			p2x,p2y = polygon[i % n]
			if y > min(p1y,p2y):
				if y <= max(p1y,p2y):
					if x <= max(p1x,p2x):
						if p1y != p2y:
							xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
						if p1x == p2x or x <= xinters:
							inside = not inside
		p1x,p1y = p2x,p2y

		return inside
		
	def inside_area(self, point):
		for place in self.circles.keys():
			if self.inside_circle(self.circles[place], point):
				return place

		for place in self.polygons.keys():
			if self.inside_polygon(self.polygons[place], point):
				return place
		
		return None
		
	def calc_distance(self, points):
		if len(points) < 2:
			return 0

		distance = 0
		xi, yi = points[0][1]
		for point in points[1:]:
			xf , yf = point[1]
			distance = distance + math.hypot(xf - xi, yf - yi)
			xi, yi = xf, yf

		return distance

	def calc_polygon_center(self, polygon):
		if len(polygon) < 2:
			return None

		min_x, min_y = polygon[0]
		max_x, max_y = polygon[0]
		for point in polygon[1:]:
			if point[0] < min_x:
				min_x = point[0]
			elif point[0] > max_x:
				max_x = point[0]
			if point[1] < min_y:
				min_y = point[1]
			elif point[1] > max_y:
				max_y = point[1]
				
		center = (min_x + int((max_x - min_x) / 2),
					min_y + int((max_y - min_y) / 2))

		return center
